home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / 031-040 / amok35 / patmatch / patmatch.mod < prev    next >
Text File  |  1993-11-04  |  5KB  |  238 lines

  1. (*---------------------------------------------------------------------------
  2.     :Program.     PatMatch.mod
  3.     :Contents.      Match filenames exaktly like AmigaDos
  4.     :Author.      Bernd Preusing
  5.     :Address.      Gerhardstr. 16  D-2200 Elmshorn
  6.     :Phone.      04121/22486
  7.     :Copyright.      Public Domain
  8.     :Language.      Modula-2
  9.     :Translator.  M2Amiga V3.3d
  10.     :Support.      Translated from BCPL and C
  11.     :History.      V 1.0 10-Feb-90 Bernd Preusing
  12.     :Remark.      Took long time to find some hints!
  13.     :Remark.      This is fully reentrant!
  14.     :Remark.      Do NOT compile with $ S-! It's recursive!
  15.     :Bugs.      Due to some tricks it will surely NOT run on M2Amiga V5.x!
  16. ---------------------------------------------------------------------------*)
  17. IMPLEMENTATION MODULE PatMatch;
  18.  
  19. FROM SYSTEM    IMPORT    ADR, BYTE, ADDRESS, CAST, INLINE (*,ASSEMBLE*);
  20.  
  21. CONST EOS = 0C;
  22.       BuffSize=128;
  23.  
  24. TYPE
  25.      UByte = [0..255];
  26.  
  27. (* $F- checked! *)
  28.  
  29. (* $E- $F- Fastest and shortest ever seen! *)
  30. PROCEDURE Length(Str:ARRAY OF CHAR):INTEGER;
  31. BEGIN
  32.   INLINE( 4CDFH,0700H, 200AH, 2200H, 4A19H, 57C9H,0FFFCH, 9041H, 4ED0H);
  33.   (* Would you like this:? (I LOVE it!)
  34.   ASSEMBLE(
  35.     MOVEM.L (A7)+,A0-A2 (* A0=ret A1=Str A2=HIGH=len-1 *)
  36.     MOVE.L    A2,D0
  37.     MOVE.L  D0,D1
  38.     Lp:    TST.B   (A1)+
  39.     DBEQ    D1,Lp
  40.     SUB.W    D1,D0      (* Even true, if no 0C at the end! *)
  41.     JMP     (A0)
  42.     END);
  43.    *)
  44. END Length;
  45. (* $F= *)
  46.  
  47.  
  48. (* $E- $F- Trick! Ändert die Parameter! Siehe Match!*)
  49. PROCEDURE CmplPat(Pat:ARRAY OF CHAR;
  50.           VAR Aux:ARRAY OF BYTE):BOOLEAN;
  51. END CmplPat;
  52. (* $F= *)
  53. PROCEDURE cmplPat(VAR Pat:ARRAY OF CHAR;
  54.           VAR Aux:ARRAY OF UByte):BOOLEAN;
  55. VAR
  56.   Ch: CHAR;
  57.   PatP: INTEGER;
  58.   Patlen: INTEGER;
  59.   ErrFlag: BOOLEAN;
  60.  
  61. (* $S- *)
  62.  
  63.   PROCEDURE Rch();
  64.   BEGIN
  65.     IF PatP>=Patlen THEN
  66.       Ch:=EOS
  67.     ELSE
  68.       Ch:=Pat[PatP];
  69.       INC(PatP);
  70.     END;
  71.   END Rch;
  72.  
  73.   PROCEDURE NextItem;
  74.   BEGIN
  75.     IF Ch="'" THEN Rch END;
  76.     Rch;
  77.   END NextItem;
  78.  
  79.   PROCEDURE SetExits(List, Val:INTEGER);
  80.   VAR A: INTEGER;
  81.   BEGIN
  82.     REPEAT
  83.       A:=Aux[List];
  84.       Aux[List]:=Val;
  85.       List:=A;
  86.     UNTIL List=0;
  87.   END SetExits;
  88.  
  89.   PROCEDURE Join(A,B: INTEGER):INTEGER;
  90.   VAR T: INTEGER;
  91.   BEGIN
  92.     T:=A;
  93.     IF A=0 THEN RETURN B END;
  94.     WHILE Aux[A]#0 DO A:=Aux[A] END;
  95.     Aux[A]:=B;
  96.     RETURN T;
  97.   END Join;
  98.  
  99. (* $S= *)
  100.  
  101.   PROCEDURE Exp(AltP:INTEGER):INTEGER;
  102.   FORWARD;
  103.  
  104.   PROCEDURE Prim():INTEGER;
  105.   VAR A: INTEGER;
  106.       Op: CHAR;
  107.   BEGIN
  108.     A:=PatP;
  109.     Op:=Ch;
  110.     NextItem;
  111.     IF Op='#' THEN
  112.       SetExits(Prim(),A)
  113.     ELSIF Op='(' THEN
  114.       A:=Exp(A);
  115.       IF Ch#')' THEN ErrFlag:=TRUE END;
  116.       NextItem;
  117.     ELSIF (Op=EOS) OR (Op='|') OR (Op=')') THEN
  118.       ErrFlag:=TRUE
  119.     END;
  120.     RETURN A;
  121.   END Prim;
  122.  
  123.   PROCEDURE Exp(AltP:INTEGER):INTEGER;
  124.   VAR Exits, A:INTEGER;
  125.   BEGIN
  126.     Exits:=0;
  127.     LOOP
  128.       A:=Prim();
  129.       IF (Ch='|') OR (Ch=')') OR (Ch=EOS) THEN
  130.         Exits:=Join(Exits,A);
  131.         IF Ch#'|' THEN RETURN Exits END;
  132.         Aux[AltP]:=PatP;
  133.         AltP:=PatP;
  134.         NextItem;
  135.       ELSE
  136.         SetExits(A,PatP);
  137.       END;
  138.     END; (* LOOP *)
  139.   END Exp;
  140.  
  141. VAR i:INTEGER;
  142.  
  143. BEGIN
  144.   PatP:=0;
  145.   Patlen:=Length(Pat);
  146.   ErrFlag:=FALSE;
  147.   FOR i:=0 TO Patlen DO Aux[i]:=0 END;
  148.   Rch;
  149.   SetExits(Exp(0),0);
  150.   RETURN ~ErrFlag;
  151. END cmplPat;
  152.  
  153.  
  154. (* $E- $F- läuft in nächste Proc hinein, spart viel Stack, da Str und Pat
  155.  *       nicht verändert werden!
  156.  *)
  157. PROCEDURE Match(Pat:ARRAY OF CHAR;
  158.         VAR Aux: ARRAY OF BYTE; Str:ARRAY OF CHAR):BOOLEAN;
  159. END Match;
  160. (* $F= *)
  161. PROCEDURE match(VAR Pat:ARRAY OF CHAR;
  162.         VAR Aux: ARRAY OF UByte; VAR Str:ARRAY OF CHAR):BOOLEAN;
  163. VAR
  164.   StrIndex, I, N, Strlength: INTEGER;
  165.   P, Q: UByte;
  166.   K, Ch: CHAR;
  167.   Succflag: BOOLEAN;
  168.   Wp: INTEGER;
  169.   Work: ARRAY[0..BuffSize-1] OF UByte;
  170.  
  171. (* $S- *)
  172.   PROCEDURE Put(N: UByte);
  173.   TYPE IntPtr  = POINTER TO UByte;
  174.   VAR ip, to: IntPtr;
  175.   BEGIN
  176.     IF N=0 THEN
  177.       Succflag:=TRUE
  178.     ELSE
  179.       ip:=ADR(Work[1]);
  180.       to:=ADR(Work[Wp]);
  181.       WHILE CAST(LONGINT,ip)<=CAST(LONGINT,to) DO
  182.         IF ip^=N THEN RETURN END;
  183.         INC(ip);
  184.       END;
  185.       INC(Wp); Work[Wp]:=N;
  186.     END;
  187.   END Put;
  188.  
  189. (* $S= needs much stack! *)
  190. BEGIN (* Match *)
  191.   StrIndex:=0;
  192.   Wp:=0;
  193.   Succflag:=FALSE;
  194.   Strlength:=Length(Str);
  195.   Put(1);
  196.   IF Aux[0]#0 THEN Put(Aux[0]) END;
  197.   LOOP
  198.     N:=1;
  199.     WHILE N<=Wp DO
  200.       P:=Work[N];
  201.       K:=Pat[P-1];
  202.       Q:=Aux[P];
  203.       IF (K='#') THEN
  204.         Put(P+1); Put(Q);
  205.       ELSIF (K='%') THEN
  206.         Put(Q)
  207.       ELSIF (K='(') OR (K='|') THEN
  208.         Put(P+1);
  209.         IF Q#0 THEN Put(Q) END;
  210.       END;
  211.       INC(N);
  212.     END;
  213.     IF StrIndex>=Strlength THEN RETURN Succflag END;
  214.     IF Wp=0 THEN RETURN FALSE END;
  215.     Ch:=Str[StrIndex]; INC(StrIndex);
  216.     N:=Wp;
  217.     Wp:=0;
  218.     Succflag:=FALSE;
  219.     I:=1;
  220.     WHILE I<=N DO
  221.       P:=Work[I];
  222.       K:=Pat[P-1];
  223.       IF (K='?') THEN
  224.         Put(Aux[P]);
  225.       ELSIF (K='#') OR (K='|') OR (K='%') OR (K='(') THEN
  226.         (* nix! *)
  227.       ELSE
  228.         IF K="'" THEN K:=Pat[P] END;
  229.     IF CAP(Ch)=CAP(K) THEN Put(Aux[P]) END;
  230.       END;
  231.       INC(I);
  232.     END;
  233.   END; (* LOOP *)
  234. END match;
  235.  
  236. (* $S- *)
  237. END PatMatch.mod
  238.